import java.lang.reflect.Array;

public class HashCodeUtil {

	public static final int SEED = 17;

	public static int hash(int seed, boolean bool) {
		return firstTerm(seed) + (bool ? 1 : 0);
	}

	public static int hash(int seed, char ch) {
		return firstTerm(seed) + (int) ch;
	}

	public static int hash(int seed, int i) {
		return firstTerm(seed) + i;
	}

	public static int hash(int seed, long l) {
		return firstTerm(seed) + (int) (l ^ (l >>> 32));
	}

	public static int hash(int seed, float f) {
		return hash(seed, Float.floatToIntBits(f));
	}

	public static int hash(int seed, double d) {
		return hash(seed, Double.doubleToLongBits(d));
	}

	public static int hash(int seed, Object obj) {
		int result = seed;
		if (obj == null) {
			result = hash(result, 0);
		} else if (!isArray(obj)) {
			result = hash(result, obj.hashCode());
		} else {
			int length = Array.getLength(obj);
			for (int idx = 0; idx < length; ++idx) {
				Object item = Array.get(obj, idx);

				if (!(item == obj))
					// recursive call!
					result = hash(result, item);
			}
		}
		return result;
	}

	// PRIVATE
	private static final int fODD_PRIME_NUMBER = 37;

	private static int firstTerm(int seed) {
		return fODD_PRIME_NUMBER * seed;
	}

	private static boolean isArray(Object obj) {
		return obj.getClass().isArray();
	}

}
